home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr25 / dkb32.zip / DKB32SRC.ZIP / TRACE.C < prev    next >
C/C++ Source or Header  |  1992-07-23  |  21KB  |  676 lines

  1. /*****************************************************************************
  2. *
  3. *                                     trace.c
  4. *
  5. *   from DKBTrace (c) 1990  David Buck
  6. *
  7. *  This module contains the entry routine for the raytracer and the code to
  8. *  parse the parameters on the command line.
  9. *
  10. *
  11. * This software is freely distributable. The source and/or object code may be
  12. * copied or uploaded to communications services so long as this notice remains
  13. * at the top of each file.  If any changes are made to the program, you must
  14. * clearly indicate in the documentation and in the programs startup message
  15. * who it was who made the changes. The documentation should also describe what
  16. * those changes were. This software may not be included in whole or in
  17. * part into any commercial package without the express written consent of the
  18. * author.  It may, however, be included in other public domain or freely
  19. * distributed software so long as the proper credit for the software is given.
  20. *
  21. * This software is provided as is without any guarantees or warranty. Although
  22. * the author has attempted to find and correct any bugs in the software, he
  23. * is not responsible for any damage caused by the use of the software.  The
  24. * author is under no obligation to provide service, corrections, or upgrades
  25. * to this package.
  26. *
  27. * Despite all the legal stuff above, if you do find bugs, I would like to hear
  28. * about them.  Also, if you have any comments or questions, you may contact me
  29. * at the following address:
  30. *
  31. *     David Buck
  32. *     22C Sonnet Cres.
  33. *     Nepean Ontario
  34. *     Canada, K2H 8W7
  35. *
  36. *  I can also be reached on the following bulleton boards:
  37. *
  38. *     OMX              (613) 731-3419
  39. *     Mystic           (613) 596-4249  or  (613) 596-4772
  40. *
  41. *  Fidonet:   1:163/109.9
  42. *  Internet:  dbuck@ccs.carleton.ca
  43. *  The "You Can Call Me RAY" BBS    (708) 358-5611
  44. *
  45. *  IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
  46. *
  47. *     The "You Can Call Me RAY" BBS (708) 358-5611
  48. *     The Information Exchange BBS  (708) 945-5575
  49. *
  50. *****************************************************************************/
  51.  
  52. #include <ctype.h>
  53. #include <time.h>
  54. #include "frame.h"        /* common to ALL modules in this program */
  55. #include "dkbproto.h"
  56.  
  57. #define MAX_FILE_NAMES 1
  58. unsigned int Options;
  59. int Quality;
  60.  
  61. FILE *bfp;
  62.  
  63. extern FRAME Frame;
  64.  
  65. char Input_File_Name[FILE_NAME_LENGTH], Output_File_Name[FILE_NAME_LENGTH];
  66.  
  67. #define MAX_LIBRARIES 10
  68. char *Library_Paths[MAX_LIBRARIES];
  69. int Library_Path_Index;
  70.  
  71. FILE_HANDLE *Output_File_Handle;
  72. int File_Buffer_Size;
  73. static int Number_Of_Files;
  74. DBL VTemp;
  75. DBL Antialias_Threshold;
  76. int First_Line, Last_Line;
  77. int Display_Started = FALSE;
  78.  
  79. /* Stats kept by the ray tracer: */
  80. long Number_Of_Pixels, Number_Of_Rays, Number_Of_Pixels_Supersampled;
  81. long Ray_Sphere_Tests, Ray_Sphere_Tests_Succeeded;
  82. long Ray_Plane_Tests, Ray_Plane_Tests_Succeeded;
  83. long Ray_Triangle_Tests, Ray_Triangle_Tests_Succeeded;
  84. long Ray_Quadric_Tests, Ray_Quadric_Tests_Succeeded;
  85. long Ray_Quartic_Tests, Ray_Quartic_Tests_Succeeded;
  86. long Bounding_Region_Tests, Bounding_Region_Tests_Succeeded;
  87. long Calls_To_Noise, Calls_To_DNoise;
  88. long Shadow_Ray_Tests, Shadow_Rays_Succeeded;
  89. long Reflected_Rays_Traced, Refracted_Rays_Traced;
  90. long Transmitted_Rays_Traced;
  91.  
  92. char DisplayFormat, OutputFormat;
  93.  
  94. extern time_t  Start_Time, Previous_Time;
  95.  
  96. void main (argc, argv)
  97.   int argc;
  98.   char **argv;
  99.   {
  100.   register int i;
  101.  
  102.   STARTUP_DKB_TRACE
  103.  
  104.   printf ("\n\n          DKB Ray Trace   Version 2.12\n");
  105.   printf ("          ----------------------------\n\n");
  106.   printf ("        Copyright (c) 1991  David K. Buck\n\n");
  107.   printf ("  Written by:\n");
  108.   printf ("  David K. Buck (dbuck@ccs.carleton.ca) (CIS: 70521, 1371)\n");
  109.   printf ("  22C Sonnet Cr.  Nepean, Ontario\n");
  110.   printf ("  Canada, K2H 8W7\n\n");
  111.   printf ("  This program is freely distributable.\n\n");
  112.  
  113.   printf ("  Conversion to IBM P.C. w/TARGA output and\n");
  114.   printf ("  other various improvements by Aaron A. Collins\n\n");
  115.  
  116.   printf ("  GIF format file reader by Steve A. Bennett\n\n");
  117.  
  118.   printf ("  Noise and DNoise functions by Robert Skinner\n\n");
  119.  
  120.   printf ("  Quartic (4th order) Shapes by Alexander Enzmann\n\n");
  121.  
  122.     printf ("  Conversion to OS/2 2.0 using icc and additional time\n");
  123.     printf ("  statistics by Michael Caldwell (mcaldwel@netcom.com).\n");
  124.  
  125.   PRINT_OTHER_CREDITS
  126.  
  127. /* Parse the command line parameters */
  128.   if (argc == 1)
  129.      usage();
  130.  
  131.   init_vars();
  132.  
  133.   Output_File_Name[0]='\0';
  134.  
  135.   Library_Paths[0] = NULL;
  136.   Library_Path_Index = 0;
  137.  
  138. /* Read the default parameters from trace.def */
  139.   get_defaults();
  140.  
  141.   for (i = 1 ; i < argc ; i++ )
  142.     if ((*argv[i] == '+') || (*argv[i] == '-'))
  143.       parse_option(argv[i]);
  144.     else
  145.       parse_file_name(argv[i]);
  146.  
  147.    if (Last_Line == -1)
  148.       Last_Line = Frame.Screen_Height;
  149.  
  150.    if (Options & DISKWRITE) {
  151.       switch (OutputFormat) {
  152.          case '\0':
  153.          case 'd':
  154.          case 'D':
  155.                    if ((Output_File_Handle = Get_Dump_File_Handle()) == NULL) {
  156.                       close_all();
  157.                       exit(1);
  158.                       }
  159.                    break;
  160. /*
  161.          case 'i':
  162.          case 'I':
  163.                    if ((Output_File_Handle = Get_Iff_File_Handle()) == NULL) {
  164.                       close_all();
  165.                       exit(1);
  166.                       }
  167.                    break;
  168.  
  169. */
  170.          case 'r':
  171.          case 'R':
  172.                    if ((Output_File_Handle = Get_Raw_File_Handle()) == NULL) {
  173.                       close_all();
  174.                       exit(1);
  175.                       }
  176.                    break;
  177.  
  178.          case 't':
  179.          case 'T':
  180.                    if ((Output_File_Handle = Get_Targa_File_Handle()) == NULL) {
  181.                       close_all();
  182.                       exit(1);
  183.                       }
  184.                    break;
  185.  
  186.          default:
  187.                    fprintf (stderr, "Unrecognized output file format %c\n", OutputFormat);
  188.                    exit(1);
  189.          }
  190.  
  191.       if (Output_File_Name[0] == '\0')
  192.          strcpy (Output_File_Name, Default_File_Name (Output_File_Handle));
  193.       }
  194.  
  195.    Print_Options();
  196.  
  197.    Initialize_Tokenizer(Input_File_Name);
  198.    printf ("Parsing...\n");
  199.    Parse (&Frame);
  200.    Terminate_Tokenizer();
  201.  
  202.   if (Options & DISPLAY)
  203.     {
  204.     printf ("Displaying...\n");
  205.     display_init(Frame.Screen_Width, Frame.Screen_Height);
  206.     Display_Started = TRUE;
  207.     }
  208.  
  209. /* Get things ready for ray tracing */
  210.    if (Options & DISKWRITE)
  211.       if (Options & CONTINUE_TRACE) {
  212.          if (Open_File (Output_File_Handle, Output_File_Name,
  213.                  &Frame.Screen_Width, &Frame.Screen_Height, File_Buffer_Size,
  214.                  READ_MODE) != 1) {
  215.             fprintf (stderr, "Error opening output file\n");
  216.             close_all();
  217.             exit(1);
  218.             }
  219.  
  220.          initialize_renderer();
  221.          Read_Rendered_Part();
  222.          }
  223.       else {
  224.          if (Open_File (Output_File_Handle, Output_File_Name,
  225.                  &Frame.Screen_Width, &Frame.Screen_Height, File_Buffer_Size,
  226.                  WRITE_MODE) != 1) {
  227.             fprintf (stderr, "Error opening output file\n");
  228.             close_all();
  229.             exit(1);
  230.             }
  231.  
  232.          initialize_renderer();
  233.          }
  234.   else
  235.      initialize_renderer();
  236.  
  237.   pq_init();
  238.   Initialize_Noise();
  239.  
  240. /* Ok, go for it - trace the picture */
  241.   if (!(Options & DISPLAY))
  242.       printf ("Rendering...\n");
  243.   Start_Tracing ();
  244.  
  245. /* Wait for a CR if the user requested it. */
  246.  
  247. /* Clean up and leave */
  248.   display_finished();
  249.  
  250.   close_all ();
  251.  
  252.   FINISH_DKB_TRACE
  253.   }
  254.  
  255. /* Print out usage error message */
  256.  
  257. void usage ()
  258.     {
  259.     printf ("\nUsage:");
  260.     printf ("\n   trace  [+/-] Option1 [+/-] Option2");
  261.     printf ("\n");
  262.     printf ("\n Options:");
  263.     printf ("\n    dx = display in format x");
  264.     printf ("\n    v  = verbose");
  265.     printf ("\n    p  = prompt exit");
  266.     printf ("\n    x  = enable early exit by key hit");
  267.     printf ("\n    fx = write output file in format x");
  268.     printf ("\n         ft - Uncompressed Targa-24  fd - DKB/QRT Dump  fr - 3 Raw Files");
  269.     printf ("\n    a  = perform antialiasing");
  270.     printf ("\n    c  = continue aborted trace");
  271.     printf ("\n    qx = image quality 0=rough, 9=full");
  272.     printf ("\n    lxxx = library path prefix");
  273.     printf ("\n    wxxx = width of the screen");
  274.     printf ("\n    hxxx = height of the screen");
  275.     printf ("\n    sxxx = start at line number xxx");
  276.     printf ("\n    exxx = end at line number xxx");
  277.     printf ("\n    bxxx = Use xxx kilobytes for output file buffer space");
  278.     printf ("\n    ifilename = input file name");
  279.     printf ("\n    ofilename = output file name");
  280.     printf ("\n\n");
  281.     exit(1);
  282.     }
  283.  
  284. void init_vars()
  285.   {
  286.   Output_File_Handle = NULL;
  287.   File_Buffer_Size = 0;
  288.   Options = 0;
  289.   Quality = 9;
  290.   Number_Of_Files = 0;
  291.   First_Line = 0;
  292.   Last_Line = -1;
  293.  
  294.   Number_Of_Pixels = 0L;
  295.   Number_Of_Rays = 0L;
  296.   Number_Of_Pixels_Supersampled = 0L;
  297.   Ray_Sphere_Tests = 0L;
  298.   Ray_Sphere_Tests_Succeeded = 0L;
  299.   Ray_Plane_Tests = 0L;
  300.   Ray_Plane_Tests_Succeeded = 0L;
  301.   Ray_Triangle_Tests = 0L;
  302.   Ray_Triangle_Tests_Succeeded = 0L;
  303.   Ray_Quadric_Tests = 0L;
  304.   Ray_Quadric_Tests_Succeeded = 0L;
  305.   Ray_Quartic_Tests = 0L;
  306.   Ray_Quartic_Tests_Succeeded = 0L;
  307.   Bounding_Region_Tests = 0L;
  308.   Bounding_Region_Tests_Succeeded = 0L;
  309.   Calls_To_Noise = 0L;
  310.   Calls_To_DNoise = 0L;
  311.   Shadow_Ray_Tests = 0L;
  312.   Shadow_Rays_Succeeded = 0L;
  313.   Reflected_Rays_Traced = 0L;
  314.   Refracted_Rays_Traced = 0L;
  315.   Transmitted_Rays_Traced = 0L;
  316.  
  317.   Frame.Screen_Height = 100;
  318.   Frame.Screen_Width = 100;
  319.  
  320.   Antialias_Threshold = 0.3;
  321.   strcpy (Input_File_Name, "object.dat");
  322.   return;
  323.   }
  324.  
  325. /* Close all the stuff that has been opened. */
  326. void close_all ()
  327.    {
  328.    if ((Options & DISPLAY) && Display_Started)
  329.      display_close();
  330.  
  331.    if (Output_File_Handle)
  332.       Close_File (Output_File_Handle);
  333.    }
  334.  
  335. /* Read the default parameters from trace.def*/
  336. void get_defaults()
  337.   {
  338.   FILE *defaults_file;
  339.   char Option_String[256], *Option_String_Ptr;
  340.  
  341.   if ((defaults_file = fopen("trace.def", "r")) != NULL) {
  342.      while (fgets(Option_String, 256, defaults_file) != NULL)
  343.         read_options(Option_String);
  344.      fclose (defaults_file);
  345.      }
  346.  
  347.   if ((Option_String_Ptr = getenv("DKBOPT")) != NULL)
  348.      read_options(Option_String_Ptr);
  349.   }
  350.  
  351. void read_options (Option_Line)
  352.   char *Option_Line;
  353.   {
  354.   register int c, String_Index, Option_Started;
  355.   short Option_Line_Index = 0;
  356.   char Option_String[80];
  357.  
  358.   String_Index = 0;
  359.   Option_Started = FALSE;
  360.   while ((c = Option_Line[Option_Line_Index++]) != '\0')
  361.     {
  362.     if (Option_Started)
  363.       if (isspace(c))
  364.         {
  365.         Option_String[String_Index] = '\0';
  366.         parse_option (Option_String);
  367.         Option_Started = FALSE;
  368.     String_Index = 0;
  369.         }
  370.      else
  371.        Option_String[String_Index++] = (char) c;
  372.  
  373.     else /* Option_Started */
  374.       if ((c == (int) '-') || (c == (int) '+'))
  375.         {
  376.         String_Index = 0;
  377.         Option_String[String_Index++] = (char) c;
  378.         Option_Started = TRUE;
  379.         }
  380.       else
  381.         if (!isspace(c))
  382.           {
  383.           fprintf (stderr, "\nBad default file format.  Offending char: (%c), val: %d.\n", (char) c, c);
  384.           exit (1);
  385.           }
  386.     }
  387.  
  388.   if (Option_Started)
  389.     {
  390.     Option_String[String_Index] = '\0';
  391.     parse_option (Option_String);
  392.     }
  393.   }
  394.  
  395. /* parse the command line parameters */
  396. void parse_option (Option_String)
  397.   char *Option_String;
  398.   {
  399.   register int Add_Option;
  400.   unsigned int Option_Number;
  401.   DBL threshold;
  402.  
  403.   if (*(Option_String++) == '-')
  404.     Add_Option = FALSE;
  405.   else
  406.     Add_Option = TRUE;
  407.  
  408.   switch (*Option_String)
  409.     {
  410.     case 'B':
  411.     case 'b':  sscanf (&Option_String[1], "%d", &File_Buffer_Size);
  412.                File_Buffer_Size *= 1024;
  413.                if (File_Buffer_Size < BUFSIZ)
  414.                   File_Buffer_Size = BUFSIZ;
  415.                Option_Number = 0;
  416.                break;
  417.  
  418.     case 'C':
  419.     case 'c':  Option_Number = CONTINUE_TRACE;
  420.                break;
  421.  
  422.     case 'D':
  423.     case 'd':  Option_Number = DISPLAY;
  424.                DisplayFormat = (char)toupper(Option_String[1]);
  425.                if (DisplayFormat == '\0')
  426.                   DisplayFormat = '0';
  427.                break;
  428.  
  429.     case 'V':
  430.     case 'v':  Option_Number = VERBOSE;
  431.                break;
  432.  
  433.     case 'W':
  434.     case 'w':  sscanf (&Option_String[1], "%d", &Frame.Screen_Width);
  435.            Option_Number = 0;
  436.                break;
  437.  
  438.     case 'H':
  439.     case 'h':  sscanf (&Option_String[1], "%d", &Frame.Screen_Height);
  440.            Option_Number = 0;
  441.                break;
  442.  
  443.     case 'F':
  444.     case 'f':  Option_Number = DISKWRITE;
  445.                if (isupper(Option_String[1]))
  446.                   OutputFormat = (char)tolower(Option_String[1]);
  447.                else
  448.                   OutputFormat = Option_String[1];
  449.  
  450.                /* Default the output format to raw. */
  451.                if (OutputFormat == '\0')
  452.                   OutputFormat = DEFAULT_OUTPUT_FORMAT;
  453.                break;
  454.  
  455.     case 'P':
  456.     case 'p':  Option_Number = PROMPTEXIT;
  457.                break;
  458.  
  459.     case 'I':
  460.     case 'i':  strncpy (Input_File_Name, &Option_String[1], FILE_NAME_LENGTH);
  461.            Option_Number = 0;
  462.                break;
  463.  
  464.     case 'O':
  465.     case 'o':  strncpy (Output_File_Name, &Option_String[1], FILE_NAME_LENGTH);
  466.            Option_Number = 0;
  467.                break;
  468.  
  469.     case 'A':
  470.     case 'a':  Option_Number = ANTIALIAS;
  471.                if (sscanf (&Option_String[1], DBL_FORMAT_STRING, &threshold) != EOF)
  472.                    Antialias_Threshold = threshold;
  473.                break;
  474.  
  475.     case 'X':
  476.     case 'x':  Option_Number = EXITENABLE;
  477.                break;
  478.  
  479.  
  480.     case 'L':
  481.     case 'l':  if (Library_Path_Index >= MAX_LIBRARIES) {
  482.                   fprintf (stderr, "Too many library directories specified\n");
  483.                   exit(1);
  484.                   }
  485.  
  486.                Library_Paths [Library_Path_Index] = malloc (strlen(Option_String));
  487.            if (Library_Paths [Library_Path_Index] == NULL) {
  488.           fprintf (stderr, "Cannot allocate memory for library pathname\n");
  489.           exit(1);
  490.           }
  491.                strcpy (Library_Paths [Library_Path_Index], &Option_String[1]);
  492.                Library_Path_Index++;
  493.            Option_Number = 0;
  494.                break;
  495.  
  496.     case 'S':
  497.     case 's':  sscanf (&Option_String[1], "%d", &First_Line);
  498.            Option_Number = 0;
  499.                break;
  500.  
  501.     case 'E':
  502.     case 'e':  sscanf (&Option_String[1], "%d", &Last_Line);
  503.            Option_Number = 0;
  504.                break;
  505.  
  506.     case 'Q':
  507.     case 'q':  sscanf (&Option_String[1], "%d", &Quality);
  508.            Option_Number = 0;
  509.                break;
  510.  
  511.                /* Turn on debugging print statements. */
  512.     case 'Z':
  513.     case 'z':  Option_Number = DEBUGGING;
  514.                break;
  515.  
  516.     default:   fprintf (stderr, "\nInvalid option: %s\n\n", --Option_String);
  517.            Option_Number = 0;
  518.     }
  519.  
  520.   if (Option_Number != 0)
  521.       if (Add_Option)
  522.            Options |= Option_Number;
  523.       else Options &= ~Option_Number;
  524.   }
  525.  
  526. void Print_Options()
  527.    {
  528.    int i;
  529.  
  530.    printf ("Options in effect: ");
  531.  
  532.    if (Options & CONTINUE_TRACE)
  533.       printf ("+c ");
  534.    else
  535.       printf ("-c ");
  536.  
  537.    if (Options & DISPLAY)
  538.       printf ("+d%c ", DisplayFormat);
  539.    else
  540.       printf ("-d ");
  541.  
  542.    if (Options & VERBOSE)
  543.       printf ("+v ");
  544.    else
  545.       printf ("-v ");
  546.  
  547.    if (Options & DISKWRITE)
  548.       printf ("+f%c ", OutputFormat);
  549.    else
  550.       printf ("-f ");
  551.  
  552.    if (Options & PROMPTEXIT)
  553.       printf ("+p ");
  554.    else
  555.       printf ("-p ");
  556.  
  557.    if (Options & EXITENABLE)
  558.       printf ("+x ");
  559.    else
  560.       printf ("-x ");
  561.  
  562.    if (Options & ANTIALIAS)
  563.       printf ("+a%f ", Antialias_Threshold);
  564.    else
  565.       printf ("-a ");
  566.  
  567.    if (Options & DEBUGGING)
  568.       printf ("+z ");
  569.  
  570.    if (File_Buffer_Size != 0)
  571.       printf ("-b%d ", File_Buffer_Size/1024);
  572.  
  573.    printf ("-q%d -w%d -h%d -s%d -e%d\n-i%s ",
  574.            Quality, Frame.Screen_Width, Frame.Screen_Height,
  575.            First_Line, Last_Line, Input_File_Name);
  576.  
  577.    if (Options & DISKWRITE)
  578.       printf ("-o%s ", Output_File_Name);
  579.  
  580.    for (i = 0 ; i < Library_Path_Index ; i++)
  581.       printf ("-l%s ", Library_Paths[i]);
  582.  
  583.    printf ("\n");
  584.    }
  585.  
  586. void parse_file_name (File_Name)
  587.   char *File_Name;
  588.   {
  589.   FILE *defaults_file;
  590.   char Option_String[256];
  591.  
  592.   if (++Number_Of_Files > MAX_FILE_NAMES)
  593.     {
  594.     fprintf (stderr, "\nOnly %d file names are allowed in a command line.", 
  595.              MAX_FILE_NAMES);
  596.     exit(1);
  597.     }
  598.  
  599.   if ((defaults_file = fopen(File_Name, "r")) != NULL) {
  600.      while (fgets(Option_String, 256, defaults_file) != NULL)
  601.         read_options(Option_String);
  602.      fclose (defaults_file);
  603.      }
  604.   }
  605.  
  606. void print_line_stats (register int y) {
  607.     time_t      Current_Time;
  608.     time_t      Time;
  609.     time_t      Temp;
  610.  
  611.     Current_Time = time (NULL);
  612. /* keep the number of "\n"s down to 25 */
  613.     printf ("\n");
  614.     printf ("Statistics for line %04d\n", y);
  615.     printf ("------------------------\n\n");
  616.     printf ("# Rays: %10ld   # Pixels: %10ld   # Pixels supersampled: %10ld\n\n",
  617.                 Number_Of_Rays, Number_Of_Pixels, Number_Of_Pixels_Supersampled);
  618.     printf ("Intersection Tests:   Type          Tests    Succeeded\n");
  619.     printf ("                      ----     ----------   ----------\n");
  620.     printf ("                      Sphere   %10ld   %10ld\n", Ray_Sphere_Tests, Ray_Sphere_Tests_Succeeded);
  621.     printf ("                      Plane    %10ld   %10ld\n", Ray_Plane_Tests, Ray_Plane_Tests_Succeeded);
  622.     printf ("                      Triangle %10ld   %10ld\n", Ray_Triangle_Tests, Ray_Triangle_Tests_Succeeded);
  623.     printf ("                      Quadric  %10ld   %10ld\n", Ray_Quadric_Tests, Ray_Quadric_Tests_Succeeded);
  624.     printf ("                      Quartic  %10ld   %10ld\n", Ray_Quartic_Tests, Ray_Quartic_Tests_Succeeded);
  625.     printf ("                      Bounds   %10ld   %10ld\n\n", Bounding_Region_Tests, Bounding_Region_Tests_Succeeded);
  626.     printf ("   Calls to Noise:         %10ld\n", Calls_To_Noise);
  627.     printf ("   Calls to DNoise:        %10ld\n", Calls_To_DNoise);
  628.     printf ("   Shadow Ray Tests:       %10ld\n", Shadow_Ray_Tests);
  629.     printf ("   Blocking Objects Found: %10ld\n", Shadow_Rays_Succeeded);
  630.     printf ("   Reflected Rays:         %10ld\n", Reflected_Rays_Traced);
  631.     printf ("   Refracted Rays:         %10ld\n", Refracted_Rays_Traced);
  632.     printf ("   Transmitted Rays:       %10ld\n", Transmitted_Rays_Traced);
  633.     Time = Current_Time - Previous_Time;
  634.    printf ("   Time for this line:     %02dd", Temp = Time / 86400);
  635.     printf (" %02dh", Temp = (Time -= Temp * 86400) / 3600);
  636.     printf (" %02dm", Temp = (Time -= Temp * 3600) / 60);
  637.     printf (" %02ds\n", Time - Temp * 60);
  638.     Time = Current_Time - Start_Time;
  639.    printf ("   Total elapsed time:     %02dd", Temp = Time / 86400);
  640.     printf (" %02dh", Temp = (Time -= Temp * 86400) / 3600);
  641.     printf (" %02dm", Temp = (Time -= Temp * 3600) / 60);
  642.     printf (" %02ds\n", Time - Temp * 60);
  643.     Time = (Current_Time - Start_Time) / (y + 1);
  644.    printf ("   Average time per line:  %02dd", Temp = Time / 86400);
  645.     printf (" %02dh", Temp = (Time -= Temp * 86400) / 3600);
  646.     printf (" %02dm", Temp = (Time -= Temp * 3600) / 60);
  647.     printf (" %02ds", Time - Temp * 60);
  648.    Previous_Time = time (NULL);
  649.     printf ("                    I/O %ds\n", Previous_Time - Current_Time);
  650. }
  651.  
  652. /* Find a file in the search path. */
  653.  
  654. FILE *Locate_File (filename, mode)
  655.    char *filename, *mode;
  656.    {
  657.    FILE *f;
  658.    int i;
  659.    char pathname[FILE_NAME_LENGTH];
  660.  
  661.    /* Check the current directory first. */
  662.    if ((f = fopen (filename, mode)) != NULL)
  663.       return (f);
  664.  
  665.    for (i = 0 ; i < Library_Path_Index ; i++) {
  666.       strcpy (pathname, Library_Paths[i]);
  667.       if (FILENAME_SEPARATOR != NULL)
  668.          strcat (pathname, FILENAME_SEPARATOR);
  669.       strcat (pathname, filename);
  670.       if ((f = fopen (pathname, mode)) != NULL)
  671.          return (f);
  672.       }
  673.  
  674.    return (NULL);
  675.    }
  676.